﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Controls.Interfaces;
using Silvermoon.UI;
using Silvermoon.Windows;
using Silvermoon.Controls.Toolbars;
using System.Diagnostics;

namespace Silvermoon.Controls
{
    /// <summary>
    /// Abstract base class for toolbars.
    /// </summary>
    public abstract class ToolbarBase : CompositeControlBase
    {
        #region const

        public const int ToolbarSize = 80;
        public const int MAXMENUHEIGHT = 480 - ToolbarSize;
        private const int EXPANDED_BIT = 1;
        private const int BUTTONSVISIBLE_BIT = 2;

        #endregion
        #region fields

        private int bitmask;
        private Orientation orientation;
        private float buttonVisibility = 0f;

        #endregion
        #region ctors/dtors

        public ToolbarBase()
            : base()
        {
            Height = ToolbarSize;
            ControlFlags |= ControlFlags.HitTestVisible;
        }


        #endregion
        #region accessors

        public static PropertyAccessor<ToolbarBase, float> ButtonVisibilityProperty = PropertyAccessor.Register<ToolbarBase, float>("ButtonVisibility",
            c => c.ButtonVisibility,
            (c, v) => c.ButtonVisibility = v);

        #endregion
        #region props

        public bool AreButtonsShown
        {
            get
            {
                return (bitmask & BUTTONSVISIBLE_BIT) != 0;
            }
            private set
            {
                bitmask = value ? bitmask | BUTTONSVISIBLE_BIT : bitmask & ~BUTTONSVISIBLE_BIT;
            }
        }

        public bool AreButtonsHidden
        {
            get
            {
                return (bitmask & BUTTONSVISIBLE_BIT) == 0;
            }
        }

        /// <summary>
        /// Gets the maximum height for the menu.
        /// </summary>
        protected virtual int MaxMenuHeight
        {
            get { return MAXMENUHEIGHT; }
        }

        /// <summary>
        /// Gets or sets whether the menu is expanded.
        /// </summary>
        public bool IsExpanded
        {
            get { return (bitmask & EXPANDED_BIT) != 0; }
            set
            {
                if (IsExpanded != value)
                {
                    bitmask = value ? bitmask | EXPANDED_BIT : bitmask & ~EXPANDED_BIT;
                    OnExpansionChanged();
                }
            }
        }


        /// <summary>
        /// Gets the window that holds the toolbar.
        /// </summary>
        public new Window Window { get; set; }

        /// <summary>
        /// Gets the collapsed height or width (depending on the screen's orientation) for the toolbar. 
        /// </summary>
        public virtual int CollapsedSize
        {
            get { return ToolbarSize; }
        }

        /// <summary>
        /// Used for toolbar transitioning within a range of -1f and 1f where 0f is the default value.
        /// </summary>
        /// <value></value>
        public float ButtonVisibility
        {
            get { return buttonVisibility; }
            set
            {
                if (buttonVisibility != value)
                {
                    buttonVisibility = value;
                    OnButtonVisibilityChanged();

                }
            }
        }

        /// <summary>
        /// Gets whether the toolbar allows landscape mode.
        /// </summary>
        public virtual bool EnableLandscape
        {
            get { return false; }
        }

        protected internal Orientation Orientation
        {
            get { return orientation; }
            set
            {
                if (value == Orientation.Landscape && !EnableLandscape) value = Orientation.Portrait;
                if (orientation != value)
                {
                    orientation = value;
                    OnOrientationChanged();
                }
            }
        }

        /// <summary>
        /// Gets the desired width or height (depending on the screen's orientation) that the toolbar is about to transition to.
        /// This value informs the window about the required size for ClientBounds.
        /// See also <seealso cref="P:CurrentSize"/> property.
        /// </summary>
        public virtual int DesiredSize
        {
            get { return ToolbarSize; }
        }

        /// <summary>
        /// Gets the width or height (depending on screen's orientation) of the toolbar that is currently transitioned.
        /// See also <seealso cref="P:DesiredSize"/> property.
        /// </summary>
        public virtual int CurrentSize
        {
            get { return ToolbarSize; }
        }

        public override bool CanFocus
        {
            get { return false; }
        }

        /// <summary>
        /// Hides the buttons.
        /// </summary>
        /// <param name="animated">true to hide in an animation, otherwise false.</param>
        public virtual void HideButtons(bool animated)
        {
            if (IsDisposing) return;
            if (AreButtonsShown)
            {
                AreButtonsShown = false;
                if (animated && IsInitialized)
                {
                    SetState(ToolbarStateManagers.ButtonsHidden);
                }
                else
                {
                    ButtonVisibilityProperty.StopAnimation(this);
                    buttonVisibility = 1;
                }
            }
        }

        /// <summary>
        ///  Shows the buttons.
        /// </summary>
        /// <param name="animated">true to show in an animation, otherwise false.</param>
        public virtual void ShowButtons(bool animated)
        {
            if (IsDisposing) return;
            if (!AreButtonsShown)
            {
                AreButtonsShown = true;
                if (animated && IsInitialized)
                {
                    SetState(ToolbarStateManagers.ButtonsShown);
                }
                else
                {
                    ButtonVisibilityProperty.StopAnimation(this);
                    buttonVisibility = 0f;
                }
            }
        }

        protected virtual void OnButtonsHidden()
        {
            if (ButtonsHidden != null) ButtonsHidden(this, EventArgs.Empty);
        }

        protected virtual void OnButtonsShown()
        {
            if (ButtonsShown != null) ButtonsShown(this, EventArgs.Empty);
        }

        protected virtual void OnWindowChanging(Window oldValue, Window newValue)
        {
        }

        protected internal override void OnTouchDown(TouchEventArgs e)
        {
            e.Handled = true;
            e.Handled = true;
            base.OnTouchDown(e);
        }

        protected internal override void OnTap(TapEventArgs e)
        {
            e.Handled = true;
            base.OnTap(e);
        }

        protected virtual void OnExpansionChanged()
        {
            SetState(IsExpanded ? "Expanded" : "Collapsed");
            if (Window != null) Window.UpdateClientBounds();
        }

        protected virtual void OnButtonVisibilityChanged()
        {
            switch ((int)buttonVisibility)
            {
                case 0: OnButtonsShown(); break;
                case 1:
                case -1: OnButtonsHidden(); break;
            }
        }

        protected virtual void OnOrientationChanged()
        {
            Invalidate(InvalidationFlag.Layout);
        }

        #endregion
        #region events

        public event EventHandler ButtonsHidden;
        public event EventHandler ButtonsShown;

        #endregion

    }
}
